package com.foxchen.textinputapp.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foxchen.textinputapp.dto.CheckCodeDTO;
import com.foxchen.textinputapp.dto.CheckCodeTimeDTO;
import com.foxchen.textinputapp.dto.TableUserDTO;
import com.foxchen.textinputapp.exception.BaseException;
import com.foxchen.textinputapp.po.TableOrg;
import com.foxchen.textinputapp.po.TableUser;
import com.foxchen.textinputapp.service.TableOrgService;
import com.foxchen.textinputapp.service.TableUserService;
import com.foxchen.textinputapp.mapper.TableUserMapper;
import com.foxchen.textinputapp.vo.LoginVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
* @author Administrator
* @description 针对表【table_user】的数据库操作Service实现
* @createDate 2024-05-17 15:00:05
*/
@Service
@Slf4j
public class TableUserServiceImpl extends ServiceImpl<TableUserMapper, TableUser>
    implements TableUserService{
    @Resource
    private TableOrgService tableOrgService;


    private static final ConcurrentHashMap<String, TableUserDTO> LOGIN_USER_MAP = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, CheckCodeTimeDTO> UUID_TIME_MAP = new ConcurrentHashMap<>();
    static {
        Runnable clearThread = () -> {
          while (true) {
              try {
                  TimeUnit.MINUTES.sleep(1L);

                  List<String> needRmKey = new ArrayList<>();
                  long currentTimeMillis = System.currentTimeMillis();
                  UUID_TIME_MAP.forEach((uuid,codeBean) -> {
                      if(currentTimeMillis - codeBean.getTime() > 60 * 1000){
                          needRmKey.add(uuid);
                      }
                  });

                  UUID_TIME_MAP.keySet().removeAll(needRmKey);
                  log.debug("clear success.keys={}",needRmKey);
              } catch (Exception e){
                  log.error("clear thread deal error.",e);
              }
          }
        };

        new Thread(clearThread).start();
    }



    @Override
    public TableUserDTO login(LoginVO loginVO) {
        CheckCodeTimeDTO checkCodeTimeDTO = UUID_TIME_MAP.get(loginVO.getUuid());
        if(null == checkCodeTimeDTO || System.currentTimeMillis() - checkCodeTimeDTO.getTime() > 60 * 1000){
            throw new BaseException("验证码已过期!");
        }

        if(!checkCodeTimeDTO.getCode().equals(loginVO.getCode())){
            UUID_TIME_MAP.remove(loginVO.getUuid());
            throw new BaseException("验证码错误!");
        }
        String password = MD5.create().digestHex16(loginVO.getPassword());
        TableUser tableUser = lambdaQuery()
                .eq(TableUser::getAccount, loginVO.getAccount())
                .eq(TableUser::getPassword, password)
                .one();
        if(null == tableUser){
            throw new BaseException("账号或密码错误!");
        }

        TableOrg orgInfo = tableOrgService.getById(tableUser.getOrgId());

        StpUtil.login(tableUser.getId());
        String tokenValue = StpUtil.getTokenValue();
        TableUserDTO tableUserDTO = TableUserDTO
                .builder()
                .id(tableUser.getId())
                .name(tableUser.getUsername())
                .token(tokenValue)
                .orgId(tableUser.getOrgId())
                .orgName(orgInfo.getOrgName())
                .build();
        LOGIN_USER_MAP.put(tokenValue,tableUserDTO);
        return tableUserDTO;
    }

    @Override
    public CheckCodeDTO getCheckCode() {
        // 唯一标识
        String uuid = UUID.randomUUID().toString();

        // 验证码base64
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        String code = lineCaptcha.getCode();

        UUID_TIME_MAP.put(uuid, CheckCodeTimeDTO.builder().code(code).time(System.currentTimeMillis()).build());

        String imageBase64Data = lineCaptcha.getImageBase64Data();

        return CheckCodeDTO.builder().uuid(uuid).code(imageBase64Data).build();
    }
}




